﻿using BackgroundTasks.Code;
using BackgroundTasks.DataModel;
using FantasyWereld.Common;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Background;
using Windows.Data.Xml.Dom;
using Windows.Storage;
using Windows.UI.Notifications;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;


namespace BackgroundTasks
{
    public sealed class FWTileUpdater : IBackgroundTask
    {
        public async void Run(IBackgroundTaskInstance taskInstance)
        {
            BackgroundTaskDeferral deferal = taskInstance.GetDeferral();

            // Read reviews from XML File
            XmlDocument _FWDataFile = await Utility.ReadXMLDocumentFromFileAsync(Constants.XML_REVIEWS_FILE_NAME);

            // Update badge info
            await UpdateBadgeInfo(_FWDataFile);

            deferal.Complete();
        }

        /// <summary>
        /// Update badge info
        /// This is a copy of the Main program function in Utility class file
        /// </summary>
        private static async Task UpdateBadgeInfo(XmlDocument _allItems)
        {
            // Fetch template
            XmlDocument badgeXml = BadgeUpdateManager.GetTemplateContent(BadgeTemplateType.BadgeNumber);
            XmlElement badgeElement = (XmlElement)badgeXml.SelectSingleNode("/badge");

            int newValue = await CountFantasyWereldNewItemsAsync(_allItems);

            // Set roaming value to new value
            ApplicationData.Current.RoamingSettings.Values["BadgeValue"] = newValue;

            if (newValue == 0)
            {
                // Something went wrong so we will clear the value just for safety
                BadgeUpdateManager.CreateBadgeUpdaterForApplication().Clear();
            }
            else
            {
                // Set badge value
                badgeElement.SetAttribute("value", newValue.ToString());
                BadgeNotification badge = new BadgeNotification(badgeXml);
                BadgeUpdateManager.CreateBadgeUpdaterForApplication().Update(badge);

                // Send notification
                Utility.SendNotification(Constants.MESSAGE_NOTIFICATION_HEADER, Constants.MESSAGE_NOTIFICATION_NEW_REVIEWS, Constants.NOTIFICATION_REVIEWS);                
            }
        }

        /// <summary>
        /// Count new items on FantasyWereld website
        /// This is a copy of the Main program function in FWDataSource class file
        /// </summary>
        private static async Task<int> CountFantasyWereldNewItemsAsync(XmlDocument _allItems)
        {
            try
            {
                // Retrieve RSS feed information from Fantasy Wereld webserver
                return await ProcessItemsInFeedAsync(Constants.RSSFEED_LATEST, _allItems);
            }
            catch
            {
                return 0;
            }
        }
        
        /// <summary>
        /// Count number of items in a feed 
        /// </summary>
        /// <param name="feedName"></param>
        /// <param name="_allReviews"></param>
        /// <returns></returns>
        private static async Task<int> ProcessItemsInFeedAsync(string feedName, XmlDocument _allItems)
        {
            int numberOfItems = 0;
            var myFeed = await Utility.GetRSSFeedAsync(feedName);

            foreach (var channel in myFeed)
            {
                foreach (var item in channel.Items)
                {
                    // Search on Link
                    var nodeList = _allItems.GetElementsByTagName("Link");
                    XmlElement node = null;

                    if (nodeList.Count > 0)
                        // Find the node with this id from the data file
                        node = FindNode(nodeList, item.Link);

                    if ((node == null) && !item.Link.Contains("nieuwsbericht"))
                    {
                        numberOfItems += 1;
                    }
                }
            }

            return numberOfItems;
        }

        private static XmlElement FindNode(XmlNodeList list, string nodeName)
        {
            if (list.Count > 0)
                foreach (XmlElement node in list)
                    if (node.InnerText.Equals(nodeName)) return node;
            return null;
        }

    }
}
